說明一大段 capture
的實作
最後來講講 assign
的實作部分
檢查參數:
escape closure
MemberAccessExprSyntax
: a.b.c
-> c
IdentifierExprSyntax
: a
-> a
refFunctionMethodInstance
是 instance function
public final class AssignClosureVisitor: SyntaxVisitor {
private(set) var results: [AssignClosureVisitorResult] = []
public let client: SKClient
public init(client: SKClient) {
self.client = client
super.init(viewMode: .sourceAccurate)
}
/// self.def(self.abc)
///
/// calledExpression self.def/def
/// MemberAccessExpr/IdentifierExpr
/// argumentList
/// TupleExprElementSyntax expression
/// TupleExprElementSyntax
override public final func visit(_ node: FunctionCallExprSyntax) -> SyntaxVisitorContinueKind {
find(node)
return .visitChildren
}
@inline(__always)
private final func find(_ node: FunctionCallExprSyntax) {
let info = client.functionInfo(node)
for param in node.argumentList {
guard let identifier: TokenSyntax = param.expression.tokenSyntax else { continue }
if let name = param.label?.text, let info {
if info.isEscape(name) {
add(identifier,
"Assign Instance Function To Escaping Closure Argument")
}
} else {
add(identifier, "Assign Instance Function To Argument")
}
}
}
private func add(_ token: TokenSyntax, _ reason: String) {
guard let isRIF = try? client(token).isRefInstanceFunction, isRIF else {
return
}
results.append(AssignClosureVisitorResult(
location: client(location: token),
reason: reason))
}
}